package util;

import java.util.List;

import org.opencv.core.Mat;
import org.opencv.highgui.Highgui;

import model.Pixel;

public class ImageUtil {
	
	private static final int TILE_SIZE = 125;

	public static Pixel[] imageToPixels(String path) {
		Mat image = Highgui.imread(path, Highgui.CV_LOAD_IMAGE_COLOR);
		return imageToPixels(image);
	}

	public static Pixel[] imageToPixels(Mat image) {
		Pixel[] pixels = new Pixel[image.cols() * image.rows()];
		int index = 0;
		for (int i = 0; i < image.cols(); i++) {
			for (int j = 0; j < image.rows(); j++) {
				double[] color = image.get(j, i);
				pixels[index] = new Pixel(i, j, color[0], color[1], color[2]);
				index++;
			}
		}
		return pixels;

	}

	public static void saveSegment(String path, List<Pixel> pixels,
			Mat originalImage) {
		Mat image = new Mat(originalImage.size(), originalImage.type());

		for (int i = 0; i < originalImage.rows(); i++) {
			for (int j = 0; j < originalImage.cols(); j++) {
				image.put(i, j, new byte[] { 0, 0, 0 });
			}

		}
		for (Pixel pixel : pixels) {
			int x = pixel.getX();
			int y = pixel.getY();

			double[] color = originalImage.get(y, x);

			image.put(y, x, color);

		}

		Highgui.imwrite(path, image);
	}

	public static Mat[] tileImage(Mat imagem) {

		int numeroColunas = imagem.cols();
		int numeroLinhas = imagem.rows();

		int tileColuna = (int) Math
				.ceil((double) numeroColunas / TILE_SIZE);
		int tileLinha = (int) Math.ceil((double) numeroLinhas / TILE_SIZE);

		int numeroTiles = tileColuna * tileLinha;
		Mat[] tiles = new Mat[numeroTiles];

		int indice = 0;
		for (int i = 0; i < tileColuna; i++) {
			for (int j = 0; j < tileLinha; j++) {
				int inicioCol = i * TILE_SIZE;
				int fimCol = inicioCol + TILE_SIZE;
				if (fimCol > imagem.cols()) {
					fimCol = imagem.cols();
				}
				Mat aux = imagem.colRange(inicioCol, fimCol);

				int inicioRow = j * TILE_SIZE;
				int fimRow = inicioRow + TILE_SIZE;
				if (fimRow > imagem.rows()) {
					fimRow = imagem.rows();
				}
				Mat tile = aux.rowRange(inicioRow, fimRow);

				tiles[indice] = tile;
				indice++;
			}
		}

		return tiles;
	}
	
	public static  Mat montarMosaico(Mat[] tiles, int largura, int altura, int type) {
		int coluna = 0;
		int linha = 0;
		Mat result = new Mat(altura, largura, type);
		
		for (int i = 0; i < tiles.length; i++) {
			if(linha >= altura){
				linha = 0;
				coluna += TILE_SIZE;
			}
			
			if(coluna >= largura){
				coluna = 0;
			}
			
			Mat tile = tiles[i];
			for (int j = 0; j <  tile.rows(); j++) {
				for (int j2 = 0; j2 < tile.cols(); j2++) {
					result.put(linha+j, coluna+j2, tile.get(j, j2));
				}
				
			}
			linha += TILE_SIZE;
		}
		return result;
		
	}
	
	public static double[] getPrecisionRecallFMeasure(Mat mask, Mat imageResult){
		double relevantMask = 0;
		double relevantResult = 0;
		double equalResult = 0;
		double resultValid = 0;
		
		for (int i = 0; i < mask.cols(); i++) {
			for (int j = 0; j < mask.rows(); j++) {
				double[] color = mask.get(j, i);
				if(isRelevant(color)){
					relevantMask++;
				}
				double[] colorResult = imageResult.get(j, i);
				boolean relevantPixelResult = isRelevant(colorResult);
				if(relevantPixelResult){
					relevantResult++;
				}
				boolean equalsRelevance = equalsRelevance(color, colorResult);
				if(relevantPixelResult && equalsRelevance){
					resultValid++;
				}
			}
		}
		
		//TODO: terminar
		double precision = resultValid/relevantResult;
		double recall = resultValid/relevantMask;
		double fmeasure = (2 * precision * recall)/(precision + recall);
		return new double[]{precision, recall, fmeasure};  
		
	}
	
	private static boolean isRelevant(double[] color){
		double r = color[0];
		double g = color[1];
		double b = color[2];
		if(r < 50 & g < 50 & b < 50){
			return true;
		}
		return false;
	}
	
	private static boolean equalsRelevance(double[] a, double[] b){		
		return isRelevant(a) && isRelevant(b);
	}

}
